#include <54func.h>
//取消机制带来了资源的泄露，因此最好的情况就是谁申请的资源谁进行释放

//函数指针类型转换,转换为统一的类型
void freep1(void *arg)
{
    printf("free p1\n");
    free((int *)arg);//将传入的指针进行强制类型转换
}
void freep2(void *arg)
{
    printf("free p2\n");
    free((int *)arg);
}
void closefd(void *arg)
{
    //传入的是文件描述符的地址，先将指针进行强制类型转换为int，再解引用关闭
    int * pfd = (int *)arg;
    printf("close fd\n");
    close(*pfd);
}
void *threadFunc(void *arg)
{
    //为防止取消导致资源泄露，因此我们再资源申请的时候就将其资源释放压入栈中，再栈中传入函数指针和其参数
    int *p1 = (int *)malloc(sizeof(int));
    //在这里，pthread_cleanup_push传入的参数是清理函数的指针和参数->函数指针，那么不同的函数指针类型传入会非常麻烦
    //     因此这里将不同类型的函数指针转换为 void 函数名(void *),同种类型，便于参数的传入
    pthread_cleanup_push(freep1,p1);
    int *p2 = (int *)malloc(sizeof(int));
    pthread_cleanup_push(freep2,p2);
    int fd = open("file",O_RDONLY);
    pthread_cleanup_push(closefd,&fd);

    //....
    //free(p1);//传入的是指针
    //freep1(p1);
    pthread_cleanup_pop(1);//填写整数即可，0表示
    //free(p2);
    //freep2(p2);
    pthread_cleanup_pop(1);
    //close(fd);//后续应该传入的其地址
    //closefd(&fd);
    pthread_cleanup_pop(1);
    printf("---------------------\n");
    pthread_exit(NULL);//线程的主动释放
}
int main()
{
    pthread_t tid;
    pthread_create(&tid,NULL,threadFunc,NULL);//子线程的创建

    pthread_join(tid,NULL);//回收子线程资源
    return 0;


    //总结：1、申请资源的同时就将资源释放函数放入到《资源清理栈》中，
    //         由于线程具有并发性，虽然再申请资源和压栈的过程中会存在线程的终止，但是压栈不是取消点，只要申请了资源，必定优雅站
    //      2、”---“之前的清理行为是有线程主动调用弹栈导致的，而"--"之后的清理行为是由于线程终止导致的
    //      3、return NULL;不会弹栈
    //      4、弹栈：参数0：表示只弹栈不执行
    //               参数>0：表示弹栈并执行
    //      5、pthread_exit/被取消且运行到取消点：弹出所有元素，没弹一个，执行清理
    //      6、资源释放顺序：后进先出
}
